package com.cxh.mediasessiondemo;

import android.media.MediaMetadata;
import android.media.MediaPlayer;
import android.media.browse.MediaBrowser;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.service.media.MediaBrowserService;
import android.webkit.WebView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.List;

/**
 * Created by Cxh
 * Time : 2021/10/23  00:18
 * Desc :
 */
public class MusicPlayerService extends MediaBrowserService implements IMediaData, Handler.Callback {
    private static final String TAG = "MusicPlayerService";

    private static final int MSG_HEARTBEAT = 1;
    private static final int HEARTBEAT_DELAY = 1000;

    private MediaSession mMediaSession;
    private MusicDataManager mDataManager;
    private NotificationHelper mNotificationHelper;
    private MediaPlayer mMediaPlayer;
    private Handler mHandler;

    @Override
    public void onCreate() {
        super.onCreate();
        mDataManager = new MusicDataManager(this);

        mMediaSession = new MediaSession(this, TAG);
        mMediaSession.setCallback(mSessionCb);
        // 设置token，触发client回调onConnect()
        setSessionToken(mMediaSession.getSessionToken());

        // 显示通知
        mNotificationHelper = new NotificationHelper(this, mMediaSession.getController());
        mNotificationHelper.requestNotification();
        // 播放器
        mMediaPlayer = new MediaPlayer();
        mMediaPlayer.setLooping(false);
        mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                int loopType = mDataManager.getLoopMode();
                if (PLAY_TYPE_SINGLE != loopType) {
                    MediaBrowser.MediaItem mediaItem = mDataManager.changeToNext();
                    playMediaItem(mediaItem, true);
                }
            }
        });

        mHandler = new Handler(this);
        mHandler.sendEmptyMessageDelayed(MSG_HEARTBEAT, HEARTBEAT_DELAY);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (null != mHandler) {
            mHandler.removeCallbacksAndMessages(null);
            mHandler = null;
        }
        if (null != mNotificationHelper) {
            mNotificationHelper.cancel();
            mNotificationHelper = null;
        }
        if (null != mMediaSession) {
            mMediaSession.setCallback(null);
            mMediaSession.release();
            mMediaSession = null;
        }
        if (null != mMediaPlayer) {
            if (mMediaPlayer.isPlaying()) {
                mMediaPlayer.pause();
            }
            mMediaPlayer.stop();
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

    @Nullable
    @Override
    public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) {
        // MediaBrowser调用connect时触发，给client端分配id
        return new BrowserRoot(MEDIA_ROOT_ID, null);
    }

    @Override
    public void onLoadChildren(@NonNull String parentId, @NonNull Result<List<MediaBrowser.MediaItem>> result) {
        result.detach();
        // 加载音乐数据
        mDataManager.queryAudioList();
        // 返回数据
        result.sendResult(mDataManager.getMediaItems());
    }

    @Override
    public boolean handleMessage(@NonNull Message msg) {
        switch (msg.what) {
            case MSG_HEARTBEAT: {
                mHandler.removeMessages(MSG_HEARTBEAT);
                mHandler.sendEmptyMessageDelayed(MSG_HEARTBEAT, HEARTBEAT_DELAY);

                if (null != mMediaPlayer) {
                    int progress = mMediaPlayer.getCurrentPosition();
                    int duration = mMediaPlayer.getDuration();
                    Bundle bundle = new Bundle();
                    bundle.putInt(KEY_MEDIA_PROGRESS, progress);
                    bundle.putInt(KEY_MEDIA_DURATION, duration);
                    bundle.putInt(KEY_CURRENT_INDEX, mDataManager.getCurrentIndex());
                    mMediaSession.sendSessionEvent(ACTION_HEARTBEAT, bundle);
                    //  通知栏进度
                    mNotificationHelper.updateMediaItem(mDataManager.getCurrentItem(), mMediaPlayer.getDuration(),
                            mMediaPlayer.getCurrentPosition(), mDataManager.getLoopMode(), mMediaPlayer.isPlaying());
                }
            }
            break;
        }
        return true;
    }

    private final MediaSession.Callback mSessionCb = new MediaSession.Callback() {

        @Override
        public void onPrepareFromMediaId(String mediaId, Bundle extras) {
            super.onPrepareFromMediaId(mediaId, extras);
            MediaBrowser.MediaItem mediaItem = mDataManager.selectMediaFromMediaId(mediaId);
            if (null == mediaItem) {
                return;
            }

            boolean autoPlay = false;
            if (null != extras) {
                autoPlay = extras.getBoolean(KEY_AUTO_PLAY);
            }
            playMediaItem(mediaItem, autoPlay);
        }

        @Override
        public void onPlay() {
            super.onPlay();
            if (!mMediaPlayer.isPlaying()) {
                mMediaPlayer.start();
                mMediaSession.setPlaybackState(new PlaybackState.Builder()
                        .setState(PlaybackState.STATE_PLAYING, mMediaPlayer.getCurrentPosition(), 1)
                        .build());
                //  通知栏进度
                mNotificationHelper.updateMediaItem(mDataManager.getCurrentItem(), mMediaPlayer.getDuration(),
                        mMediaPlayer.getCurrentPosition(), mDataManager.getLoopMode(), mMediaPlayer.isPlaying());
            }
        }

        @Override
        public void onPause() {
            super.onPause();
            if (mMediaPlayer.isPlaying()) {
                mMediaPlayer.pause();
                mMediaSession.setPlaybackState(new PlaybackState.Builder()
                        .setState(PlaybackState.STATE_PAUSED, mMediaPlayer.getCurrentPosition(), 1)
                        .build());
                //  通知栏进度
                mNotificationHelper.updateMediaItem(mDataManager.getCurrentItem(), mMediaPlayer.getDuration(),
                        mMediaPlayer.getCurrentPosition(), mDataManager.getLoopMode(), mMediaPlayer.isPlaying());
            }
        }

        @Override
        public void onSkipToPrevious() {
            super.onSkipToPrevious();
            MediaBrowser.MediaItem mediaItem = mDataManager.changeToPrevious();
            if (null != mediaItem) {
                playMediaItem(mediaItem, true);
            }
        }

        @Override
        public void onSkipToNext() {
            super.onSkipToNext();
            MediaBrowser.MediaItem mediaItem = mDataManager.changeToNext();
            if (null != mediaItem) {
                playMediaItem(mediaItem, true);
            }
        }

        @Override
        public void onCustomAction(@NonNull String action, @Nullable Bundle extras) {
            super.onCustomAction(action, extras);
            switch (action) {
                case ACTION_LOOP_TYPE: {
                    int loopType = mDataManager.changeLoopMode();
                    Bundle bundle = new Bundle();
                    bundle.putInt(KEY_CURRENT_LOOP, loopType);
                    mMediaSession.sendSessionEvent(ACTION_LOOP_TYPE, bundle);
                    //  通知栏进度
                    mNotificationHelper.updateMediaItem(mDataManager.getCurrentItem(), mMediaPlayer.getDuration(),
                            mMediaPlayer.getCurrentPosition(), mDataManager.getLoopMode(), mMediaPlayer.isPlaying());
                }
                break;
                case ACTION_PROGRESS_CHANGE: {
                    if (null != extras) {
                        int progress = extras.getInt(KEY_MEDIA_PROGRESS);
                        int maxProgress = extras.getInt(KEY_SEEKBAR_MAX);
                        if (progress < maxProgress) {
                            // 播放进度
                            int realPosition = (int) ((progress / (float) maxProgress) * mMediaPlayer.getDuration());
                            mMediaPlayer.seekTo(realPosition);
                            //  通知栏进度
                            mNotificationHelper.updateMediaItem(mDataManager.getCurrentItem(), mMediaPlayer.getDuration(),
                                    mMediaPlayer.getCurrentPosition(), mDataManager.getLoopMode(), mMediaPlayer.isPlaying());
                        }
                    }
                }
                break;
            }
        }
    };

    private void playMediaItem(MediaBrowser.MediaItem mediaItem, boolean autoPlay) {
        try {
            if (mMediaPlayer.isPlaying()) {
                mMediaPlayer.pause();
            }
            mMediaPlayer.reset();
            mMediaPlayer.setDataSource(MusicPlayerService.this, mediaItem.getDescription().getMediaUri());
            mMediaPlayer.prepare();
            mMediaPlayer.seekTo(0);

            int state;
            if (autoPlay) {
                mMediaPlayer.start();
                state = PlaybackState.STATE_PLAYING;
            } else {
                state = PlaybackState.STATE_PAUSED;
            }

            // 更新客户端UI
            PlaybackState playbackState = new PlaybackState.Builder()
                    .setState(state, mMediaPlayer.getCurrentPosition(), 1)
                    .build();
            mMediaSession.setPlaybackState(playbackState);
            updateClientMetadata(mediaItem);
            // 通知栏
            mNotificationHelper.updateMediaItem(mediaItem, mMediaPlayer.getDuration(),
                    mMediaPlayer.getCurrentPosition(), mDataManager.getLoopMode(), mMediaPlayer.isPlaying());
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.e("onPrepareFromUri, error: " + e.toString());
        }
    }

    private void updateClientMetadata(MediaBrowser.MediaItem mediaItem) {
        String id = mediaItem.getDescription().getMediaId();
        String title = String.valueOf(mediaItem.getDescription().getTitle());
        String author = String.valueOf(mediaItem.getDescription().getSubtitle());
        String mediaUri = String.valueOf(mediaItem.getDescription().getMediaUri());

        MediaMetadata mediaMetadata = new MediaMetadata.Builder()
                .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, id)
                .putString(MediaMetadata.METADATA_KEY_TITLE, title)
                .putString(MediaMetadata.METADATA_KEY_ARTIST, author)
                .putString(MediaMetadata.METADATA_KEY_MEDIA_URI, mediaUri)
                .putLong(MediaMetadata.METADATA_KEY_DURATION, mMediaPlayer.getDuration())
                .build();
        mMediaSession.setMetadata(mediaMetadata);
    }

    public boolean isPlaying() {
        if (null != mMediaPlayer) {
            return mMediaPlayer.isPlaying();
        }
        return false;
    }
}
